﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace XEvolve.Core.Events
{
    public abstract class TopicBase<EventArguments> : ITopic<EventArguments> where EventArguments : EventArgs
    {
        private static readonly Predicate<EventArguments> ALL = args => true;

        private readonly IDictionary<Action<EventArguments>, Predicate<EventArguments>> handlers = new Dictionary<Action<EventArguments>, Predicate<EventArguments>>();

        public void Subscribe(Action<EventArguments> handler, Predicate<EventArguments> predicate)
        {
            lock (handlers)
            {
                if (!handlers.ContainsKey(handler))
                {
                    handlers[handler] = predicate;
                }
            }
        }

        public void Subscribe(Action<EventArguments> handler)
        {
            Subscribe(handler, ALL);
        }

        public void Unsubscribe(Action<EventArguments> handler)
        {
            lock (handlers)
            {
                if (handlers.ContainsKey(handler))
                {
                    handlers.Remove(handler);
                }
            }
        }

        protected Action<EventArguments>[] GetHandlers(EventArguments eventArgs)
        {
            lock (handlers)
            {
                return handlers.Where(pair => pair.Value(eventArgs)).Select(pair => pair.Key).ToArray();
            }
        }

        public abstract void Publish(EventArguments eventArgs);
    }
}